import paramiko
import threading
import json
import os
from queue import Queue
import time

class TerminalManager:
    def __init__(self,config_file='terminal_configs.json',tabs_file='terminal_tabs.json'):
        self.config_file = config_file
        self.tabs_file = tabs_file
        self.window = None  # 用于在终端输出时调用evaluate_jso
        self.connections = {}  # {tab_id: ssh_client}
        self.output_queues = {}  # {tab_id: Queue}
        self.load_configs()
        
    def load_configs(self):
        try:
            if os.path.exists(self.config_file):
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    self.configs = json.load(f)
            else:
                self.configs = []
        except Exception as e:
            print(f"加载终端配置失败: {e}")
            self.configs = []
        return self.configs

    def save_configs(self,configs):
        self.configs = configs
        try:
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(self.configs, f, ensure_ascii=False, indent=2)
            return True
        except Exception as e:
            print(f"保存终端配置失败: {e}")
            return False

    def connect_terminal(self, tab_id, config):
        print(f"尝试连接到: {config}")
        try:
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            ssh.connect(
                hostname=config['ip'],
                port=int(config['port']),
                username=config['username'],
                password=config['password']
            )
            # 创建并保存shell通道
            channel = ssh.invoke_shell()
            self.connections[tab_id] = {
                'ssh': ssh,
                'channel': channel
            }
            self.output_queues[tab_id] = Queue()
            # 启动监听线程
            thread = threading.Thread(
                target=self._listen_output,
                args=(tab_id, channel),
                daemon=True
            )
            thread.start()
            return True
        except Exception as e:
            print(f"连接终端失败: {e}")
            if self.window:
                # self.window.evaluate_js(f"alert('{error_msg}')")
                 self.window.evaluate_js(f"updateTerminalOutput({tab_id}, \"连接终端失败: {e}\")")
            return False

    def _listen_output(self, tab_id, channel):
        while tab_id in self.connections:
            if channel.recv_ready():
                output = channel.recv(1024).decode('utf-8')
                lines = output.replace('\r\n', '\n').replace('\r', '\n').split('\n')
                for line in lines:
                    if line:
                        self.output_queues[tab_id].put(line)
                        self.window.evaluate_js(f"updateTerminalOutput({tab_id}, {json.dumps(line)})")
            else:
                time.sleep(0.1)

    def execute_command(self, tab_id, command):
        if tab_id not in self.connections:
            return "未连接到终端"
        conn = self.connections[tab_id]
        conn['channel'].send(command + '\n')  # 通过同一个通道发送命令
        return "命令已发送"

    def disconnect_terminal(self, tab_id):
        if tab_id in self.connections:
            self.connections[tab_id].close()
            del self.connections[tab_id]
            del self.output_queues[tab_id]
            return True
        return False

    def get_output(self, tab_id):
        if tab_id not in self.output_queues:
            return ""
        output = []
        while not self.output_queues[tab_id].empty():
            output.append(self.output_queues[tab_id].get())
        return "".join(output)

    def load_terminal_tabs(self):
        try:
            if os.path.exists(self.tabs_file):
                with open(self.tabs_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
            return []
        except Exception as e:
            print(f"加载终端标签页失败: {e}")
            return []

    def save_terminal_tabs(self, tabs):
        try:
            with open(self.tabs_file, 'w', encoding='utf-8') as f:
                json.dump(tabs, f, ensure_ascii=False, indent=2)
            return True
        except Exception as e:
            print(f"保存终端标签页失败: {e}")
            return False

terminal_manager = TerminalManager()

def init_terminal_manager(window):
    terminal_manager.window = window
    window.expose(
        terminal_manager.connect_terminal,
        terminal_manager.disconnect_terminal,
        terminal_manager.execute_command,
        terminal_manager.get_output,
        terminal_manager.load_configs,
        terminal_manager.save_configs,
        terminal_manager.load_terminal_tabs,
        terminal_manager.save_terminal_tabs
    )
    return terminal_manager